// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

Shader "URP/TestPBR"
{
    Properties
    {
        _BaseMap ("Base Map", 2D) = "white" {}
        _BaseColor ("Base Color", Color) = (1,1,1,1)
        _BgColor ("Bg Color", Color) = (0,0,0,1) 
        _DialColor ("Dial Color", Color) = (0,0,0,1)
        _Metallic ("Metallic", Range(0, 1)) = 0.5
        _Roughness ("Roughness", Range(0, 1)) = 0.5
    }

    SubShader
    {
        Tags
        {
            "RenderPipeline"="UniversalPipeline"
            "RenderType"="Transparent"
            "Queue"="Transparent"
//            "IgnoreProjector"="True"
//            "CanUseSpriteAtlas"="True"
        }

        
        HLSLINCLUDE

        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

        TEXTURE2D (_BaseMap);       SAMPLER (sampler_BaseMap);

        CBUFFER_START(UnityPerMaterial)
        float4 _BaseMap_ST;
        half4 _BaseColor;
        half4 _BgColor;
        half4 _DialColor;
        half _Roughness;
        half _Metallic;
        half _TotalHP;
        half _PerUnit;
        half _Ratio;
        CBUFFER_END

        // #ifdef UNITY_DOTS_INSTANCING_ENABLED
        //     UNITY_DOTS_INSTANCING_START(MaterialPropertyMetadata)
        //         UNITY_DOTS_INSTANCED_PROP(float4, _BaseColor)
        //         UNITY_DOTS_INSTANCED_PROP(float4, _BgColor)
        //         UNITY_DOTS_INSTANCED_PROP(float4, _DialColor)
        //         UNITY_DOTS_INSTANCED_PROP(float, _Roughness)
        //         UNITY_DOTS_INSTANCED_PROP(float, _Metallic)
        //         UNITY_DOTS_INSTANCED_PROP(float, _TotalHP)
        //         UNITY_DOTS_INSTANCED_PROP(float, _PerUnit)
        //         UNITY_DOTS_INSTANCED_PROP(float, _Ratio)
        //     UNITY_DOTS_INSTANCING_END(MaterialPropertyMetadata)
        //
        //     #define _BaseColor          UNITY_ACCESS_DOTS_INSTANCED_PROP_FROM_MACRO(float4 , Metadata_BaseColor)
        //     #define _BgColor            UNITY_ACCESS_DOTS_INSTANCED_PROP_FROM_MACRO(float4 , Metadata_BgColor)
        //     #define _DialColor          UNITY_ACCESS_DOTS_INSTANCED_PROP_FROM_MACRO(float4 , Metadata_DialColor)
        //     #define _Roughness          UNITY_ACCESS_DOTS_INSTANCED_PROP_FROM_MACRO(float  , Metadata_Roughness)
        //     #define _Metallic         UNITY_ACCESS_DOTS_INSTANCED_PROP_FROM_MACRO(float  , Metadata_Metallic)
        //     #define _TotalHP            UNITY_ACCESS_DOTS_INSTANCED_PROP_FROM_MACRO(float  , Metadata_TotalHP)
        //     #define _PerUnit            UNITY_ACCESS_DOTS_INSTANCED_PROP_FROM_MACRO(float  , Metadata_PerUnit)
        //     #define _Ratio              UNITY_ACCESS_DOTS_INSTANCED_PROP_FROM_MACRO(float  , Metadata_Ratio)
        // #endif
        
        struct a2v {
            float4 positionOS : POSITION;
            float3 texcoord : TEXCOORD;
            float3 normalOS : NORMAL;
            // UNITY_VERTEX_INPUT_INSTANCE_ID 
        };

        struct v2f {
            float4 positionCS : SV_POSITION;
            float2 texcoord : TEXCOORD0;
            float4 positionWS : TEXCOORD1;
            float4 normalWS : TEXCOORD2;
            // UNITY_VERTEX_INPUT_INSTANCE_ID
        };
        ENDHLSL

        Pass
        {
            Name "Default"
            Tags{ "LightMode"="UniversalForward" }
            
            ZWrite ON
//            Blend SrcAlpha OneMinusSrcAlpha
            
            HLSLPROGRAM

            // #pragma target 4.5
            // #pragma multi_compile _ DOTS_INSTANCING_ON
            
            #pragma vertex vert
            #pragma fragment frag
            
            v2f vert(a2v i) {
                v2f o;
                UNITY_SETUP_INSTANCE_ID(i);
                UNITY_TRANSFER_INSTANCE_ID(i, o);
                o.positionWS.xyz = TransformObjectToWorld(i.positionOS.xyz);
                o.positionCS = TransformWorldToHClip(o.positionWS.xyz);
                o.normalWS.xyz = TransformObjectToWorldNormal(i.normalOS, true);
                o.texcoord = TRANSFORM_TEX(i.texcoord.xy, _BaseMap);
                return o;
            }

            half TestDirectBRDFSpecular(BRDFData brdfData, half3 normalWS, half3 lightDirectionWS, half3 viewDirectionWS)
            {
                float3 lightDirectionWSFloat3 = float3(lightDirectionWS);
                float3 halfDir = SafeNormalize(lightDirectionWSFloat3 + float3(viewDirectionWS));

                float NoH = saturate(dot(float3(normalWS), halfDir));
                half LoH = half(saturate(dot(lightDirectionWSFloat3, halfDir)));

                // GGX Distribution multiplied by combined approximation of Visibility and Fresnel
                // BRDFspec = (D * V * F) / 4.0
                // D = roughness^2 / ( NoH^2 * (roughness^2 - 1) + 1 )^2
                // V * F = 1.0 / ( LoH^2 * (roughness + 0.5) )
                // See "Optimizing PBR for Mobile" from Siggraph 2015 moving mobile graphics course
                // https://community.arm.com/events/1155

                // Final BRDFspec = roughness^2 / ( NoH^2 * (roughness^2 - 1) + 1 )^2 * (LoH^2 * (roughness + 0.5) * 4.0)
                // We further optimize a few light invariant terms
                // brdfData.normalizationTerm = (roughness + 0.5) * 4.0 rewritten as roughness * 4.0 + 2.0 to a fit a MAD.
                float d = NoH * NoH * brdfData.roughness2MinusOne + 1.00001f;
                half d2 = half(d * d);

                half LoH2 = LoH * LoH;
                half specularTerm = brdfData.roughness2 / (d2 * max(half(0.1), LoH2) * brdfData.normalizationTerm);

                return specularTerm;
            }

            half3 TestMyBRDFSpecular(half NdotH, half LdotH, half roughness)
            {
                half roughness2 = roughness * roughness;

                half d = NdotH * NdotH * (roughness2 - 1.0) + 1;
                half d2 = d * d;
                             
                return roughness2 / (d2 * max(half(0.1), LdotH * LdotH) * (roughness * 4 + 2));
            }

            half4 frag(v2f i) : SV_TARGET {
                UNITY_SETUP_INSTANCE_ID(i);
                
                float2 uv = i.texcoord.xy;
                half4 color = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, uv) * _BaseColor;
                
                Light light = GetMainLight();

                float3 N = normalize(i.normalWS.xyz);
                float3 V = normalize(GetWorldSpaceViewDir(i.positionWS));
                float3 L = normalize(light.direction);
                float3 H = normalize(V + L);

                float NdotH = saturate(dot(N, H));
                float LdotH = saturate(dot(L, H));

                half metallic = _Metallic;
                float smoothness = _Roughness;
                half oneMinusReflectivity = OneMinusReflectivityMetallic(metallic);
                
                BRDFData brdfData = (BRDFData)0;
                brdfData.albedo = color.rgb;
                brdfData.diffuse = brdfData.albedo * oneMinusReflectivity;
                brdfData.specular = lerp(kDieletricSpec.rgb, brdfData.albedo, metallic);
                brdfData.reflectivity = half(1.0) - oneMinusReflectivity;

                brdfData.perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(smoothness);
                brdfData.roughness = max(PerceptualRoughnessToRoughness(brdfData.perceptualRoughness), HALF_MIN_SQRT);
                brdfData.roughness2 = max(brdfData.roughness * brdfData.roughness, HALF_MIN);
                brdfData.normalizationTerm   = brdfData.roughness * half(4.0) + half(2.0);
                brdfData.roughness2MinusOne  = brdfData.roughness2 - half(1.0);
                float3 spec = brdfData.specular * TestDirectBRDFSpecular(brdfData, N, L, V);

                spec = metallic * TestMyBRDFSpecular(NdotH, LdotH, (1 - _Roughness) * (1 - _Roughness));
                // return half4(brdfData.specular, 1);

                return half4(spec, 1);
                return color;
            }
            ENDHLSL
        }
    }
}
